package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"regexp"
	"sync"

	consulapi "github.com/hashicorp/consul/api"
	"github.com/spf13/cobra"
	v1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
)

var config string
var namespace string
var serviceName string

func main() {
	rootCmd := &cobra.Command{
		Use: "k8sdnsquery",
		PreRun: func(cmd *cobra.Command, args []string) {
			_, err := os.Stat(config)
			if err != nil {
				log.Fatalf("配置文件 %s 不存在", config)
			}
		},
		Run: func(cmd *cobra.Command, args []string) {
			clientset := createClient(config)
			fmt.Printf("获取clientset成功\n")
			wg := sync.WaitGroup{}
			wg.Add(1)
			go watchServices(clientset, namespace, serviceName, &wg)
			wg.Wait()
		},
	}
	//添加flags
	rootCmd.Flags().StringVarP(&config, "config", "c", "/root/.kube/config", "config file")
	rootCmd.Flags().StringVarP(&namespace, "namespace", "n", "default", "namespace")
	rootCmd.Flags().StringVarP(&serviceName, "service", "s", "", "service name")
	err := rootCmd.Execute()
	if err != nil {
		log.Fatalf("Failed to execute root command: %v", err)
	}
}

func createClient(config string) *kubernetes.Clientset {
	//读取配置文件
	cfg, err := clientcmd.BuildConfigFromFlags("", config)
	if err != nil {
		log.Fatalf("Failed to build config: %v", err)
	}
	//创建clientset
	clientset, err := kubernetes.NewForConfig(cfg)
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}
	return clientset
}

// func getServices(clientset *kubernetes.Clientset, namespace string) []v1.Service {
// 	services, err := clientset.CoreV1().Services(namespace).List(context.TODO(), metav1.ListOptions{})
// 	if err != nil {
// 		log.Fatalf("Failed to get services: %v", err)
// 	}
// 	return services.Items
// }

// func getEndpointsFromService(clientset *kubernetes.Clientset, service v1.Service) {
// 	//获取service的endpoints
// 	endpoints, err := clientset.CoreV1().Endpoints(service.Namespace).Get(context.TODO(), service.Name, metav1.GetOptions{})
// 	if err != nil {
// 		log.Fatalf("Failed to get endpoints: %v", err)
// 	}
// 	//获取endpoints的ip和port
// 	for _, subset := range endpoints.Subsets {
// 		for _, port := range subset.Ports {
// 			for _, address := range subset.Addresses {
// 				fmt.Printf("ip: %s, port: %d, protocol: %s\n", address.IP, port.Port, port.Protocol)
// 			}
// 		}
// 	}
// }

// func watchPods(clientset *kubernetes.Clientset, namespace string) {
// 	watchInterface, err := clientset.CoreV1().Pods(namespace).Watch(context.TODO(), metav1.ListOptions{})
// 	if err != nil {
// 		log.Fatalf("Failed to watch pods: %v", err)
// 	}
// 	defer watchInterface.Stop()

// 	//监听pod事件
// 	fmt.Printf("开始监听pod事件\n")
// 	for event := range watchInterface.ResultChan() {
// 		pod, ok := event.Object.(*v1.Pod)
// 		if !ok {
// 			log.Fatalf("event.Object is not a Pod")
// 		}
// 		fmt.Printf("pod: %s, ip: %s, phase: %s\n", pod.Name, pod.Status.PodIP, pod.Status.Phase)
// 	}
// }

// 监听指定名字的service
func watchServices(clientset *kubernetes.Clientset, namespace string, name string, wg *sync.WaitGroup) {
	// 使用正则表达式匹配服务名
	pattern := regexp.MustCompile(name)

	watchInterface, err := clientset.CoreV1().Services(namespace).Watch(context.TODO(), metav1.ListOptions{})
	if err != nil {
		log.Fatalf("Failed to watch services: %v", err)
	}
	defer watchInterface.Stop()

	//监听service事件
	fmt.Printf("开始监听service事件，使用正则表达式: %s\n", name)
	for event := range watchInterface.ResultChan() {
		service, ok := event.Object.(*v1.Service)
		if !ok {
			log.Fatalf("event.Object is not a Service")
		}

		// 使用正则表达式匹配服务名
		if pattern.MatchString(service.Name) {
			fmt.Printf("service: %s, ip: %s, port: %d,namespace: %s\n", service.Name, service.Spec.ClusterIP, service.Spec.Ports[0].Port, service.Namespace)
			fmt.Printf("event.Type: %s\n", event.Type)
			//如果event.Type为ADDED，则注册服务
			if event.Type == "ADDED" {
				registerService(service.Name, service.Spec.ClusterIP, int(service.Spec.Ports[0].Port), service.Namespace)
			}
			//如果event.Type为DELETED，则注销服务
			if event.Type == "DELETED" {
				deregisterService(service.Name, service.Namespace)
			}
		}
	}
	wg.Done()
}

func registerService(serviceName string, serviceIP string, servicePort int, namespace string) {
	//创建consul客户端
	config := consulapi.DefaultConfig()
	config.Address = "172.31.6.101:8500"
	consulClient, err := consulapi.NewClient(config)
	if err != nil {
		log.Fatalf("Failed to create consul client: %v", err)
	}
	//定义服务注册信息
	serviceID := serviceName + "-" + namespace
	registration := &consulapi.AgentServiceRegistration{
		ID:      serviceID,
		Name:    serviceName + "-" + namespace,
		Address: serviceIP,
		Port:    servicePort,
		Tags:    []string{"go", "k8sdnsquery"},
		Check: &consulapi.AgentServiceCheck{
			TCP:      fmt.Sprintf("%s:%d", serviceIP, servicePort),
			Interval: "10s",
			Timeout:  "5s",
			Notes:    "Health check for k8sdnsquery",
		},
	}
	err = consulClient.Agent().ServiceRegister(registration)
	if err != nil {
		log.Fatalf("Failed to register service: %v", err)
	}
	fmt.Printf("服务 %s 注册成功\n", serviceName)
}

func deregisterService(serviceName string, namespace string) {
	//创建consul客户端
	config := consulapi.DefaultConfig()
	config.Address = "172.31.6.101:8500"
	consulClient, err := consulapi.NewClient(config)
	if err != nil {
		log.Fatalf("Failed to create consul client: %v", err)
	}
	//注销服务
	err = consulClient.Agent().ServiceDeregister(serviceName + "-" + namespace)
	if err != nil {
		log.Fatalf("Failed to deregister service: %v", err)
	}
	fmt.Printf("服务 %s 注销成功\n", serviceName)
}
